import { _decorator, Component, Node, game } from 'cc';
import { App } from '../../../App';
const { ccclass, property } = _decorator;
import { Ball } from '../Ball';
import { GameModel3 } from './GameModel3';
import { GameLayer3 } from './GameLayer3';
import UtilTool from '../../../tools/UtilTool';
import { showTip, showTipBox } from '../../../tools/PopuUp';
import { Vec3 } from 'cc';
import { Tween } from 'cc';
import { SYSTEM_ADDRESS } from '../GameManage';
import { GameBaseLogic, GameEndState, GamePlayState, GamePlayTip } from '../GameBaseLogic';
import { GameMulitUser } from './GameMulitUser';
import BilliardsGameController from '../controller/BilliardsGameController';
import GameRespBody from '../../../const/GameRespBody';
import { find } from 'cc';
import { Vec2 } from 'cc';

/* 游戏逻辑类 */
export class GameMulitLogic extends GameBaseLogic {
    /* 所有玩家对象数组 */
    allUserObj : GameMulitUser[] = []

    /* 游戏脚本类 */
    gameView : GameModel3 = null

    /* 游戏UI类 */
    gameLayer : GameLayer3 = null
    
    /* 游戏控制类 */
    controller : BilliardsGameController = null

    initGame() {
        this.gameView = App.Model.gameView as GameModel3
        this.gameLayer = this.gameView.gameLayerCtrl
        this.controller = this.gameView.controller as BilliardsGameController

        this.reset()

        this.curPlayUser = new GameMulitUser(SYSTEM_ADDRESS, null,[])
        let gameStartData = App.Model.gameManage.gameStartData
        for (const key in gameStartData.targetBall) {
            if (Object.prototype.hasOwnProperty.call(gameStartData.targetBall, key)) {
                let obj = new GameMulitUser(key, gameStartData.nicknameMap[key], gameStartData.targetBall[key])
                this.allUserObj.push(obj)
            }
        }
        this.setPlayState(GamePlayState.GAME_START)

        // this.gameLayer.setUserName(this.mine.getName(), this.ai.getName())
        this.updateBallInfo()
    }

    // 重新开始
    restart() {
        this.initGame()
    }

    // 游戏开始，随机决定开球方
    onGameStart() {
        // this.curPlayUser = this.mine // 默认玩家开始
        this.isHasSetBallBelogn = true
        this.showPlayTip(GamePlayTip.GAME_START)
        this.setPlayState(GamePlayState.WAIT_HIT_BALL)
        this.gameView.gameStart()

    }

    // 停止全部动作
    stopAllAction() {
        this.gameView.cueCtrl.stopAllAction()
        Tween.stopAllByTarget(this)
        Tween.stopAllByTarget(this.gameView.posBallCtrl)
        Tween.stopAllByTarget(this.gameView.posBallCtrl.node)
    }

    exitGame() {
        this.stopAllAction()
        this.gameView.removeAllEvent()
    }

    // 等待击球
    onWaitHitBall() {
        this.contactBallList.length = 0
        this.ballInRoleList.length = 0
        this.roleInballList.length = 0
        this.curPlayUser.onCue()
    }

    // 击球
    onHitBall() {
        this.setAbelBall(false)
    }

    // 设置呼吸效果
    setAbelBall(show=false) {
        // 处理自己所属球节点的呼吸效果
        if (show) {
            if (this.curPlayUser.mine) {
                for (let i = 0; i < App.Model.gameManage.otherBallArr.length; i++) {
                    const ball = App.Model.gameManage.otherBallArr[i]
                    if (ball) {
                        let ballObj = ball.getComponent(Ball)
                        if (this.curPlayUser.isBelognMine(ballObj.number)) {
                            ballObj.setAbelNode(true)
                        }
                        else{
                            ballObj.setAbelNode(false)
                        }
                    }
                }
            }
        }
        else{
            // if (this.curPlayUser.mine) {
                for (let i = 0; i < App.Model.gameManage.otherBallArr.length; i++) {
                    const ball = App.Model.gameManage.otherBallArr[i]
                    if (ball) {
                        let ballObj = ball.getComponent(Ball)
                        ballObj.setAbelNode(false)
                    }
                }
            // }
        }
        
    }

    // 击球结束
    onHitBallEnd() {
        if (this.curPlayUser.userAddress == SYSTEM_ADDRESS) {
            // 系统打完球后把球洞的开关打开
            this.gameView.setHoleSwitch(true)

            // 开球结束后通知服务器开球
            // if (App.Model.gameManage.getIsOwner()) { // 不用房主上报，用第一个玩家上报的数据，防止房主掉线了就进行不下去
                this.gameView.reqOpenBallMsg(this.gameView.gameLogic.getAllBallPos())
            // }
            
            return
        }

        if (find("holeNode",this.gameLayer.node).active) {
            // 系统打完球后把球洞的开关打开(这里是防止收到服务器的游戏状态消息了，但是自己端的击球结束还没有走，导致球洞还没有被打开)
            this.gameView.setHoleSwitch(true)
        }

        // 击打者请求上报击球结果
        // if (this.curPlayUser.mine) {
            let motherBall = this.checkIsFoul(false)
            let enterBall = this.ballInRoleList
            let allBallInfo = this.getAllBallPos()
            this.gameView.reqHitballEndMsg(motherBall, enterBall, allBallInfo, this.playWheel)
        // }
    }

    // 处理连杆提示
    handleComeCue() {
        this.comboCount += 1
        this.showPlayTip(GamePlayTip.COMB, this.comboCount)
    }

    // 处理进洞的球，那个球进了，就加谁的分数
    handleBallInRole(enterBall) {
        enterBall.forEach(ballNumber=>{
            for (let i = 0; i < this.allUserObj.length; i++) {
                const item = this.allUserObj[i] as GameMulitUser
                item.removeBall(ballNumber)
            }
        })

        this.updateBallInfo()
    }

    // 设置所有玩家的目标球
    setAllUserAllBallList(targetBall) {
        for (let i = 0; i < this.allUserObj.length; i++) {
            const item = this.allUserObj[i] as GameMulitUser
            if (targetBall[item.userAddress]) {
                item.allBallList = targetBall[item.userAddress]
            }
        }
    }

    // 设置所有玩家的剩余球
    setAllUserBallList(notEnterBall) {
        for (let i = 0; i < this.allUserObj.length; i++) {
            const item = this.allUserObj[i] as GameMulitUser
            if (notEnterBall[item.userAddress]) {
                item.ballList = notEnterBall[item.userAddress]
            }
        }

        this.updateBallInfo()
    }

    // 更新UI上的球的信息
    updateBallInfo() {
        if(!this.isHasSetBallBelogn) {
            return
        }

        if (App.Model.gameManage.isWatchGame) {
            this.gameLayer.updataSelfBall(this.curPlayUser as GameMulitUser)
        }
        else {
            this.gameLayer.updataSelfBall(this.getMyUser())
        }
        
    }

    /* 获取自己的用户对象  */
    getMyUser() {
        for (let i = 0; i < this.allUserObj.length; i++) {
            const item = this.allUserObj[i] as GameMulitUser
            if (item.mine) {
                return item
            }
        }

        return null
    }

    // 收到倒计时时间结束事件
    downTimeEndEvent() {
        if (this.gameLayer.node==null) return

        switch(this.curPlayState) {
            case GamePlayState.HIT_BALL: // 击球 不处理
                this.stopActionTime()
                return

            case GamePlayState.WAIT_HIT_BALL: // 在等待击球时，还没击球，属于犯规，交换选手摆球
                this.gameLayer.resetProgress()
                this.gameView.cueCtrl.isHitBall = false
                this.gameView.cueCtrl.resetCuePos()
                return

            case GamePlayState.WAIT_POS_BALL: // 在等待摆球时，还没摆球，属于犯规，交换选手摆球
                return
        }

        console.error("cur downTimeEndEvent play state is unhandle", this.curPlayState)
    }


    // 是否ai玩
    isAiPlay() {
        return false/* this.curPlayUser == this.ai */
    }

    // 等待摆球
    onWaitPosBall() {
        this.gameView.whiteBall.getComponent(Ball).hide()
        this.curPlayUser.posWhiteBall()
        // this.setActionTime(TrainTimeType.TIME_POS)
    }

    // 摆球结束
    onPosBallEnd() {
        if (this.curPlayUser.mine) {
            // 请求上报重新摆球的结果
            let allBallInfo = this.getAllBallPos()
            this.gameView.reqPosBallResoultMsg(allBallInfo)
        }

        this.setPlayState(GamePlayState.WAIT_HIT_BALL)
    }

    // 切换玩家
    changePlay(address="") {
        // 重置作用点
        if (this.gameView.cueCtrl.isMine) {
            this.gameLayer.setActionPoint(new Vec2(0,0))
        }  
        
        if (this.curPlayUser.userAddress == address) {
            // 当前玩家继续这一回合
            // 处理自己所属球节点的呼吸效果
            this.setAbelBall(true)
            return
        }

        this.comboCount = 0
        this.curComboClearBallList.length = 0

        for (let i = 0; i < this.allUserObj.length; i++) {
            const item = this.allUserObj[i] as GameMulitUser
            if (item.userAddress == address) {
                this.curPlayUser = item
                break
            }
        }

        showTip(App.language.getLanguageLab(149) +  "[" + UtilTool.formatNickOrAddress({"nickname":this.curPlayUser.userNickname, "address":address}) + "]" + App.language.getLanguageLab(150))
        this.gameLayer.setCurrentPlayer(this.curPlayUser.userNickname, UtilTool.getShortWalletAddr(address))

        if (App.Model.gameManage.isWatchGame) {
            this.updateBallInfo()
        }

        // 处理自己所属球节点的呼吸效果
        this.setAbelBall(this.curPlayUser.mine)
    }

    // 一轮结束
    onOneRoundEnd() {
        this.showPlayTip(GamePlayTip.NORMAL_CHANGE)
        this.setPlayState(GamePlayState.WAIT_HIT_BALL)
    }

    // 游戏结束
    onGameEnd() {
        this.gameLayer.stopTimeSchedule()

        // if(this.gameEndState == GameEndState.FAIL) {
        //     tween(this).delay(delayTime).call(()=>{                
        //         UtilTool.printLog("cur play 游戏结束，你输了")
        //         GameUtils2.showLayer(TrainLayer.FAIL)
        //     }).start()

        // } else if(this.gameEndState == GameEndState.WIN) {
            
        //     tween(this).delay(delayTime).call(()=>{
        //         UtilTool.printLog("cur play 游戏结束，你赢了")
        //         GameUtils2.showLayer(TrainLayer.WIN)
        //     }).start()
            
        // }
    }
    
    getName() : String{
        if(this.curPlayUser == null) {
            return "待定"
        }
        return this.curPlayUser.getName()
    }

    stopActionTime() {

    }

    showCombo(comboCount : number) {
        this.gameView.showCombo(this.comboCount)
    }

    reset() {
        this.stopAllAction()

        if (this.allUserObj) {
            this.allUserObj.forEach(item => {
                item.reset()
            })
        }
        

        this.ballInRoleList = []
        this.isHasSetBallBelogn = true
        this.curPlayState = GamePlayState.NONE
        this.beforePlayState = GamePlayState.NONE
        this.contactBallList = [] 
        this.comboCount = 0
        this.gameEndState = GameEndState.NONE

        /* let allBallList = App.Model.gameManage.otherBallArr.concat(this.whiteBallCtrl.node)
        allBallList.forEach((ball)=>{
            ball.getComponent(Ball).reset()
        }) */

        this.gameView.posBallCtrl.reset()

        this.ballInRoleList.length = 0
        this.contactBallList.length = 0
        this.curComboClearBallList.length = 0

        this.allUserObj = []
        this.curPlayUser = null
        
    }

    /** 通知玩家当前房间内游戏状态 */
    respGameStatusChange(gamedata) {
        let that = this
        let checkTime = 20
        if (this.gameLayer) {
            this.gameLayer.resetProgress()
        }
        
        if (gamedata.roomId == App.Model.gameManage.roomId) {

            // "roomId":"510",         // 房间号
            // "needResetWhite":false, // 是否需要重置白球位置 false不需要 true需要
            // "needRestTable":false,  // 是否需要重置球桌 true需要 false不需要
            // "enterBall":[4],        // 进洞的球号
            // "currentHitPlayer":"0xa5d3239e1da5c30b78e35d56a4b17939c8d5b932",  // 当前击球玩家
            // "countdown":30,          // 倒计时
            // "targetBall":null,      // 玩家目标球列表（map，key为玩家账号，value为目标球列表）
            // "allBallInfo":[],       // 各个球的信息

            let endFunc = function(data) {
                UtilTool.printLog("通知玩家当前房间内游戏状态",that.curPlayState)
                if (that.curPlayState == GamePlayState.HIT_BALL_END || that.curPlayState == GamePlayState.WAIT_HIT_BALL || checkTime<=0) {
                    if (that==null || that.gameView.node==null) return

                    let curData = GameRespBody.GameStatusChange_Data
                    curData.roomId = data.roomId
                    curData.wheel = data.wheel
                    curData.needResetWhite = data.needResetWhite
                    curData.needRestTable = data.needRestTable
                    curData.enterBall = data.enterBall
                    curData.currentHitPlayer = data.currentHitPlayer
                    curData.countdown = data.countdown
                    curData.targetBall = data.targetBall
                    curData.allBallInfo = data.allBallInfo

                    that.playWheel = curData.wheel

                    // 设置当前回合时间倒计时
                    that.gameLayer.setTimeAction(curData.countdown)

                    // 设置是否连杆提示
                    if (curData.currentHitPlayer==that.curPlayUser.userAddress) {
                        // 连杆
                        that.handleComeCue()
                        that.setPlayState(GamePlayState.WAIT_HIT_BALL)
                    }
                    else {
                        // 不连杆
                        if (!curData.needRestTable && !curData.needResetWhite) {
                            that.setPlayState(GamePlayState.ONE_ROUND_END)
                        }
                    }

                    // 设置当前玩家
                    that.changePlay(curData.currentHitPlayer)

                    // 位置矫正
                    that.modifyAllBallPos(curData.allBallInfo)

                    // 摆杆
                    that.curPlayUser.onCue()

                    // 是否犯规处理
                    if (curData.needRestTable) {
                        // 重置球桌（还原所有球）
                        that.showPlayTip(GamePlayTip.GAME_RESET_ALLBALL)
                        that.setPlayState(GamePlayState.WAIT_POS_BALL)

                    }
                    else if (curData.needResetWhite) {
                        // 重置母球
                        that.showPlayTip(GamePlayTip.FOUL_CHANGE)
                        that.setPlayState(GamePlayState.WAIT_POS_BALL)

                    }

                    // 玩家进球处理
                    if (curData.enterBall && curData.enterBall.length>0) {
                        that.handleBallInRole(curData.enterBall)
                    }
                }
                else{
                    checkTime = checkTime - 1
                    setTimeout(() => {
                        endFunc(data)
                    }, 200);
                }
            }

            endFunc(gamedata)
        }
    }

    /** 通知游戏断线重连 或者 观战 */
    respGameReconnect(gamedata) {
        if (gamedata.roomId == App.Model.gameManage.roomId) {
            UtilTool.printLog("正在进行断线重连初始化>>>")
            // "roomId":"510",          // 房间号 
            // "currentRoomStatus":1,   // 当前房间状态 0等待中 1开球中 2游戏中
            // "targetBall":false,      // 玩家目标球列表（map，key为玩家账号，value为目标球列表）
            // "notEnterBall":null,           // 玩家d剩余球列表（map，key为玩家账号，value为目标球列表）
            // "currentHitPlayer":"0xa5d3239e1da5c30b78e35d56a4b17939c8d5b932",  // 当前击球玩家
            // "countdown":30,          // 倒计时
            // "needResetWhite":false,  // 是否需要重置球桌 true需要 false不需要
            // "allBallInfo":[],        // 各个球的信息

            this.playWheel = gamedata.wheel
            if (gamedata.currentRoomStatus==1) {  // 开球中
                // 设置当前回合时间倒计时
                this.gameLayer.setTimeAction(-1)
                
                // 设置当前玩家
                if (this.curPlayUser.userAddress!=SYSTEM_ADDRESS) {
                    this.curPlayUser = new GameMulitUser(SYSTEM_ADDRESS, "", [])
                    this.gameLayer.setCurrentPlayer("", UtilTool.getShortWalletAddr(SYSTEM_ADDRESS))
                }

                // 位置矫正
                this.gameView.resetAllBallPos(false)

                // 设置所有玩家剩余球
                this.setAllUserBallList(gamedata.notEnterBall)

                // 设置所有玩家目标球
                this.setAllUserAllBallList(gamedata.targetBall)

                // 设置游戏状态
                this.setPlayState(GamePlayState.WAIT_HIT_BALL)

                this.gameView.goSystemPlayball()

            }
            else if (gamedata.currentRoomStatus == 2) { // 游戏中
                // 设置当前回合时间倒计时
                this.gameLayer.setTimeAction(gamedata.countdown)

                // 位置矫正
                this.modifyAllBallPos(gamedata.allBallInfo)

                // 设置当前玩家
                this.changePlay(gamedata.currentHitPlayer)

                // 摆杆
                this.curPlayUser.onCue()

                // 设置所有玩家剩余球
                this.setAllUserBallList(gamedata.notEnterBall)

                if(gamedata.needResetWhite) {
                    this.setPlayState(GamePlayState.WAIT_POS_BALL)
                }
                else {
                    this.setPlayState(GamePlayState.WAIT_HIT_BALL)
                }
            } 
        }
    }

    /** 通知玩家球杆角度发生变化 */
    respCueChange(data) {
        if (!this.curPlayUser.mine) {
            this.cue.changeCue(data.angle)
        }
    }

    /** 通知玩家当前玩家击球了 */
    respHitball(data) {
        // if (!this.curPlayUser.mine) { // 所有人都收到击球通知并处理
            this.uploadAccount = data.uploadAccount
            this.cue.cueMoveAction(data.angle, data.dynamics, 0.2)
        // }
    }

    /** 通知玩家重新摆球的结果 */
    respPosBallResoult(data) {
        if (!this.curPlayUser.mine) {
            let whiteBallInfo = data.allBallInfo.filter(item => {
                return item.num == 0
            })
            if (whiteBallInfo.length>0) {
                let whiteBallPos = new Vec3(whiteBallInfo[0].posX, whiteBallInfo[0].posY, whiteBallInfo[0].posZ) 
                this.gameView.posBallCtrl.setWhiteBallPos(whiteBallPos)
            }
        }
    }

    /** 通知房间内玩家多人游戏结束 */
    respGameEnd(data) {
        if (App.Model.gameManage.isWatchGame){
            // 观战模式
            showTip(App.language.getLanguageLab(104))
            setTimeout(() => {
                this.gameView.backToMultiRoom()
            }, 3000);
            return
        }

        this.setPlayState(GamePlayState.GAME_END)
        this.gameView.gameOver(data)
    }

    /** 通知房间已销毁 */
    respRoomDestory(data) {
        if (data.roomId == App.Model.gameManage.roomId) {
            showTipBox({
                content:App.language.getLanguageLab(138),
                func:()=>{
                    App.Model.gameView.backToMultiRoom()
                }
              })
        }
    }

    // 通知被踢出房间
    respRoomKickOut(data) {
        if (this.gameView.viewNode.getChildByName("GameEndLayer3")) {
            this.gameView.viewNode.getChildByName("GameEndLayer3").removeFromParent()
        }

        let tipData = {
            content : App.language.getLanguageLab(2030),
            func : (btnIndex) => {
                this.gameView.backToMultiRoom()
            }
        }

        showTipBox(tipData)
    }

    // 通知玩家帧数据
    respFrameData(data) {
        // 位置矫正
        if (this.curPlayState == GamePlayState.HIT_BALL) {
            this.modifyAllBallPos(data.allBallInfo,true)
        }
    }

}
